package com.chub.study.modules.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chub.RespEnum;
import com.chub.RespResult;
import com.chub.study.modules.annotation.LogRecord;
import com.chub.study.modules.entity.PsnInfo;
import com.chub.study.modules.entity.PsnInfoDTO;
import com.chub.study.modules.entity.PsnInfoVO;
import com.chub.study.modules.entity.TStudInfo;
import com.chub.study.modules.mapper.PsnInfoMapper;
import com.chub.study.modules.service.PsnInfoService;
import com.chub.study.modules.service.TStudInfoService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;


import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 人员信息表 服务实现类
 *
 * @author Chub
 * @since 2024-08-28
 */
@Slf4j
@Service
public class PsnInfoServiceImpl extends ServiceImpl<PsnInfoMapper, PsnInfo> implements PsnInfoService {

    @Autowired
    private PsnInfoMapper psnInfoMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private TStudInfoService studInfoService;


    @Override
    public IPage<PsnInfo> selectPage(PsnInfoDTO reqDto) {

        QueryWrapper<PsnInfo> queryWrapper = new QueryWrapper<>();
        // if (Objects.nonNull(reqDto)) {
        //     queryWrapper.lambda().eq(StrUtil.isNotBlank(reqDto.getRcrdId()), PsnInfo::getRcrdId, reqDto.getRcrdId());
        // }

        return psnInfoMapper.selectPage(reqDto.toPage(), queryWrapper);
    }

    /**
     * 分页查询
     *
     * @param reqDto
     * @return IPage<PsnInfo>
     */
    @LogRecord(methodDesc = "分页查询")
    // @Transactional(readOnly = true)
    @Override
    public RespResult<IPage<PsnInfo>> selectPsnInfoByPage(PsnInfoDTO reqDto) {
        IPage<PsnInfo> selectPage = psnInfoMapper.selectPsnInfoByPage(reqDto.toPage(), reqDto);
        log.info("JSON.toJSONString(selectPage) resultPage：{}", JSON.toJSONString(selectPage));

        return RespResult.success(selectPage);
    }

    // @Transactional(readOnly = true)
    @Override
    public List<PsnInfoVO> list(PsnInfoDTO reqDTO) {
        QueryWrapper<PsnInfo> queryWrapper = this.buildQuery(reqDTO);
        return this.transferVo(this.psnInfoMapper.selectList(queryWrapper));
    }

    // @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(PsnInfoDTO reqDto) {
        // TODO 唯一性字段校验
        reqDto.setRcrdId(null);
        psnInfoMapper.insert(this.transferEntity(null, reqDto));
    }

    // @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(PsnInfoDTO reqDto) {
        Assert.hasText(reqDto.getRcrdId(), "id不能为空");
        // TODO 唯一性字段校验
        PsnInfo entity = psnInfoMapper.selectById(reqDto.getRcrdId());
        Assert.notNull(entity, "找不到id为 " + reqDto.getRcrdId() + " 的记录");
        psnInfoMapper.updateById(this.transferEntity(entity, reqDto));
    }

    // @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Set<String> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            psnInfoMapper.deleteBatchIds(ids);
        }
    }

    @Override
    public PsnInfoVO detail(String id) {
        Assert.hasText(id, "id不能为空");
        PsnInfo entity = psnInfoMapper.selectById(id);
        Assert.notNull(entity, "找不到id为 " + id + " 的记录");
        return this.transferVo(entity);
    }

     private QueryWrapper<PsnInfo> buildQuery(PsnInfoDTO reqDTO) {
         QueryWrapper<PsnInfo> queryWrapper = new QueryWrapper<>();
         if (Objects.nonNull(reqDTO)) {
             queryWrapper.lambda().eq(StrUtil.isNotBlank(reqDTO.getRcrdId()), PsnInfo::getRcrdId, reqDTO.getRcrdId())
                     .eq(Objects.nonNull(reqDTO.getBrthDate()), PsnInfo::getBrthDate, reqDTO.getBrthDate());
         }
         return queryWrapper;
     }

     private PsnInfo transferEntity(PsnInfo entity, PsnInfoDTO reqDto) {
         if (Objects.isNull(entity)) {
             entity = new PsnInfo();
         }
         BeanUtils.copyProperties(reqDto, entity);
         return entity;
     }

     private List<PsnInfoVO> transferVo(List<PsnInfo> entities) {
         if (CollectionUtils.isEmpty(entities)) {
             // 返回空集合
             return Collections.emptyList();
         }

         List<PsnInfoVO> voList = entities.stream().map(entity -> {
             PsnInfoVO vo = new PsnInfoVO();
             BeanUtils.copyProperties(entity, vo);
             return vo;
         }).collect(Collectors.toList());
         return voList;
     }

     private PsnInfoVO transferVo(PsnInfo entity) {
         if (Objects.isNull(entity)) {
             return null;
         }
         PsnInfoVO vo = new PsnInfoVO();
         BeanUtils.copyProperties(entity, vo);
         return vo;
     }

    /**
     * 单元测试 分页查询
     * 代表只读，在将事务设置成只读后，相当于将数据库设置成只读数据库，此时若要进行写的操作，会出现错误。
     * 只读事务内，不能进行增、删、改操作，否则出现异常：cannot execute statement in a read-only transaction；
     * 只读事务内，同一个查询方法的多次调用查询结果一致，不会读取到其他事务修改的数据；
     *
     *
     * @param reqDto
     * @return IPage<PsnInfo>
     */
    @LogRecord(methodDesc = "分页查询")
    // @Transactional(readOnly = true)
    @Override
    public RespResult<IPage<PsnInfo>> queryPsnInfoByPage(PsnInfoDTO reqDto) {
        if (Objects.isNull(reqDto)) {
            return RespResult.error(RespEnum.PARAM_ERROR.getCode(), "请求参数不能为空");
        }
        if (Objects.isNull(reqDto.getAge())) {
            return RespResult.error(RespEnum.PARAM_ERROR.getCode(), "年龄不能为空");
        }

        LocalDate brthDate = reqDto.getBrthDate();
        int age = reqDto.getAge();
        // 这里加一个校验出生日期的判断， 单元测试的时候入参必须要有出生日期
        if(!Objects.isNull(brthDate)) {
            try {
                IPage<PsnInfo> selectPage = psnInfoMapper.selectPsnInfoByPage(reqDto.toPage(), reqDto);
                log.info("resultPage：{}", JSON.toJSONString(selectPage));
                List<PsnInfo> psnInfoList1 = objectMapper.convertValue(selectPage.getRecords(), new TypeReference<List<PsnInfo>>(){});

                if (IterUtil.isNotEmpty(psnInfoList1)) {
                    for (PsnInfo psnInfo : psnInfoList1) {
                        PsnInfo psnInfo1 = psnInfoMapper.selectById(psnInfo.getRcrdId());
                        String name = psnInfo1.getName();
                        String gend = psnInfo1.getGend();


                        switch (gend) {
                            case "男":
                                psnInfo1.setGend("男");
                                break;
                            case "女":
                                psnInfo1.setGend("女");
                                break;
                            default:
                                psnInfo1.setGend("未知");
                                break;
                        }

                        List<TStudInfo> respList;
                        QueryWrapper<TStudInfo> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("BJBH", "A02");
                        queryWrapper.like( "XSXM", "张泡泡");

                        // respList = studInfoMapper.selectList(queryWrapper);
                        respList = studInfoService.list(queryWrapper);
                        log.info("respList：{}", JSON.toJSONString(respList));


                    }
                    // psnInfoList.forEach(psnInfo -> {
                    //     log.info("psnInfo：{}", JSON.toJSONString(psnInfo));
                    // });
                }
                return RespResult.success(selectPage);
            } catch (Exception e)  {
                log.error("查询失败, {} ", e.getMessage());
            }
        }
        return RespResult.error("查询失败");
    }
}
